package com.npr.sockettest;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;

public class MainActivity extends AppCompatActivity implements View.OnClickListener, Thread.UncaughtExceptionHandler{

    public static final int SHOW_SERVER_MESSAGE = 1;
    public static final int STATE_CONNECTED = 2;
    public static final int STATE_CLOSED = 3;
    private EditText serverIp;
    private EditText serverPort;
    private EditText sendData2Server;
    private TextView displayReceiveData;
    private Button btnConnServer;
    private Socket socket;
    private boolean connectState = false;
    private String contentUI = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Thread.setDefaultUncaughtExceptionHandler(this);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        serverIp = (EditText) findViewById(R.id.server_ip);
        serverPort = (EditText) findViewById(R.id.server_port);
        sendData2Server = (EditText) findViewById(R.id.send_data);
        displayReceiveData = (TextView) findViewById(R.id.display_receive_data);
        btnConnServer = (Button) findViewById(R.id.btn_conn_server);
        Button btnSendData = (Button) findViewById(R.id.btn_send_data);
        btnConnServer.setOnClickListener(this);
        btnSendData.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_conn_server:
                connectServer();
                break;
            case R.id.btn_send_data:
                sendData();
                break;
            default:
                break;
        }
    }

    private Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case SHOW_SERVER_MESSAGE:
                    displayReceiveData.setText(contentUI);
                    break;
                case STATE_CONNECTED:
                    btnConnServer.setText("Close");
                    break;
                case STATE_CLOSED:
                    btnConnServer.setText("Connect");
                    break;
                default:
                    break;
            }
        }
    };
    /** Called when the user clicks the button connect TCP server */
    public void connectServer() {
        String btnState = btnConnServer.getText().toString();
        if (btnState.equals("Connect")) {
            connectState = true;
        }
        else {
            connectState = false;
            // close socket manually
            if (socket != null) {
                try {
                    System.out.println("Close Socket when clicked Button CLOSE");
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        // distinct connect / close
        if (connectState) {
            ReceiveThread receiveThread = new ReceiveThread();
            new Thread(receiveThread).start();
        } else {

        }
    }

    class ReceiveThread implements Runnable {
        @Override
        public void run() {
            String strIp = serverIp.getText().toString();
            int iPort = Integer.parseInt(serverPort.getText().toString());
            Message msg = new Message();
            try {
                socket = new Socket(strIp, iPort);
                msg.what = STATE_CONNECTED;
                handler.sendMessage(msg);
            } catch (IOException e) {
                e.printStackTrace();
                msg.what = STATE_CLOSED;
                handler.sendMessage(msg);
            }
            System.out.println("Create socket client successful");
            BufferedReader br = null;
            try {
                br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            } catch (IOException e) {
                e.printStackTrace();
            }
            while (connectState) {
                try {
                    contentUI = br.readLine();
                    System.out.println("Receive data from server:" + contentUI);
                    // server disconnected activityly
                    if (contentUI == null && contentUI.length() ==0) {
                        System.out.println("receive null from server and set connectState false");
                        connectState = false;
                    }
                    // message-handler notify to update UI MainThread
                    msg.what = SHOW_SERVER_MESSAGE;
                    handler.sendMessage(msg);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket != null) {
                try {
                    System.out.println("Close Socket on Thread !!!!!");
                    br.close();
                    connectState = false;
                    msg.what = STATE_CLOSED;
                    handler.sendMessage(msg);
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void sendData() {
        String message = sendData2Server.getText().toString();
        PrintWriter out = null;
        try {
            out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (socket.isConnected()) {
            System.out.println("Begin send data to server");
            out.println(message);
            out.flush();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onStart() {
        super.onStart();
    }

    @Override
    public void onStop() {
        super.onStop();
    }



    @Override
    public void uncaughtException(Thread t, Throwable e) {
        Log.i("AAA", "uncaughtException: " + e);
    }
}
